package cn.wolfcode.wolf2w.redis.service.impl;

import cn.wolfcode.wolf2w.domain.Strategy;
import cn.wolfcode.wolf2w.redis.service.IStrategyStatisVORedisService;
import cn.wolfcode.wolf2w.redis.util.RedisKeys;
import cn.wolfcode.wolf2w.redis.vo.StrategyStatisVO;
import cn.wolfcode.wolf2w.service.IStrategyService;
import cn.wolfcode.wolf2w.service.IUserInfoService;
import cn.wolfcode.wolf2w.util.DateUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class StrategyStatisVORedisServiceImpl implements IStrategyStatisVORedisService {

    @Autowired
    private StringRedisTemplate template;
    @Autowired
    private IStrategyService strategyService;
    @Autowired
    private IUserInfoService userInfoService;

    @Override
    public void viewnumIncrease(String sid, int num) {

        StrategyStatisVO vo = this.getStrategyStatisVo(sid);

        // 统一 +1   绝了
        vo.setViewnum(vo.getViewnum() + num);

        // 更新vo
        this.setStrategyStatisVo(vo);
    }

    @Override
    public StrategyStatisVO getStrategyStatisVo(String sid) {

        // 拼接key
        String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        // 判断key是否存在
        StrategyStatisVO vo = null;
        if (!template.hasKey(key)) {
            // 不存在先创建
            vo = new StrategyStatisVO();
            Strategy strategy = strategyService.get(sid);
            BeanUtils.copyProperties(strategy, vo);
            vo.setStrategyId(strategy.getId());
            // 更新vo
            this.setStrategyStatisVo(vo);
        } else {
            // 存在就取出来
            String voStr = template.opsForValue().get(key);
            vo = JSON.parseObject(voStr, StrategyStatisVO.class);
        }

        return vo;
    }

    @Override
    public void setStrategyStatisVo(StrategyStatisVO vo) {
        // 拼接key
        String key = RedisKeys.STRATEGY_STATIS_VO.join(vo.getStrategyId());
        // 更新vo
        template.opsForValue().set(key, JSON.toJSONString(vo));

    }

    @Override
    public void setTravelStatisVo(StrategyStatisVO vo) {
        // 拼接key
        String key = RedisKeys.TRAVEL_STATIS_VO.join(vo.getTravelId());
        // 更新vo
        template.opsForValue().set(key, JSON.toJSONString(vo));

    }

    @Override
    public void replynumIncrease(String sid, int num) {
        StrategyStatisVO vo = this.getStrategyStatisVo(sid);

        // 统一 +1   绝了
        vo.setReplynum(vo.getReplynum() + num);

        // 更新vo
        this.setStrategyStatisVo(vo);
    }

    @Override
    public boolean favor(String sid, String uid) {

        // 获取记号
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid);

        List<String> sidList = new ArrayList<>();
        if (template.hasKey(key)) {
            // 记号存在 直接获取
            String sidListStr = template.opsForValue().get(key);
            sidList = JSON.parseArray(sidListStr, String.class);
        }

        // 通过记号判断当前是收藏还是取消
        StrategyStatisVO vo = this.getStrategyStatisVo(sid);
        if (sidList.contains(sid)) {
            // 取消 收藏
            vo.setFavornum(vo.getFavornum() - 1);
            sidList.remove(sid);
        } else {
            // 添加 收藏
            vo.setFavornum(vo.getFavornum() + 1);
            sidList.add(sid);
        }

        // 更新记号 更新vo对象
        template.opsForValue().set(key, JSON.toJSONString(sidList));
        this.setStrategyStatisVo(vo);

        /**
         * 这个收藏列表不应该在缓存中操作
         * 因为这个也是敏感数据 用户收藏了就是收藏了 不能丢失的
         */
        System.out.println("----------------用户收藏攻略列表 redis 持久化 start----------");
        // 从redis中获取用户收藏攻略列表 sidList
        // 将列表更新至用户 数据库内的数据
        userInfoService.updateUserFavors(uid, sidList);
        System.out.println("----------------用户收藏攻略列表 redis 持久化 end----------");

        // 只有收藏了才会包含
        // 取消收藏了不会包含
        return sidList.contains(sid);
    }

    @Override
    public List<String> getUserStrategyFavor(String uid) {
        // 获取记号
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid);

        List<String> sidList = new ArrayList<>();
        if (template.hasKey(key)) {
            // 记号存在 直接获取
            String sidListStr = template.opsForValue().get(key);
            sidList = JSON.parseArray(sidListStr, String.class);
        }
        return sidList;
    }

    @Override
    public boolean strategyThumbup(String sid, String uid) {
        // 获取记号
        String key = RedisKeys.USER_STRATEGY_THUMB.join(uid, sid);

        if (!template.hasKey(key)) {
            // 不存在
            StrategyStatisVO vo = this.getStrategyStatisVo(sid);
            vo.setThumbsupnum(vo.getThumbsupnum() + 1);
            this.setStrategyStatisVo(vo);

            // 有效时间: 今天最后一秒 - 当前时间
            Date now = new Date();
            Date end = DateUtil.getEndDate(now);
            Long time = DateUtil.getDateBetween(now, end);
            template.opsForValue().set(key, "1", time, TimeUnit.SECONDS);

            return true;
        }
        return false;
    }

    @Override
    public boolean isStrategyExist(String id) {
        String key = RedisKeys.STRATEGY_STATIS_VO.join(id);

        return template.hasKey(key);
    }

    @Override
    public List<StrategyStatisVO> queryStartegyVos(boolean isTravel) {
        String key = RedisKeys.STRATEGY_STATIS_VO.join("*");
        if (isTravel) {
            key = RedisKeys.TRAVEL_STATIS_VO.join("*");
        }

        // 得到所有的vo key
        Set<String> keys = template.keys(key);
        List<StrategyStatisVO> list = new ArrayList<>();
        if (keys != null && keys.size() > 0) {
            for (String voKey : keys) {
                String voStr = template.opsForValue().get(voKey);
                StrategyStatisVO vo = JSON.parseObject(voStr, StrategyStatisVO.class);
                list.add(vo);
            }
        }

        return list;
    }
}
